package hasthi.wsdm.capabilities;

import hasthi.common.HasthiException;
import hasthi.common.XmlBeanUtils;
import hasthi.common.HasthiException.FaultCode;
import hasthi.common.constants.WSDMConstants;
import hasthi.common.constants.WSDMConstants.SystemState;
import hasthi.wsdm.Capability;
import hasthi.wsdm.CapabilityDescription;
import hasthi.wsdm.ManagableResource;
import hasthi.wsdm.ManagementAgentContext;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.xml.namespace.QName;

import org.apache.xmlbeans.XmlObject;

import edu.indiana.extreme.wsdm.PiggybackParameterListDocument;

/**
 * When this capability is enabled, it will collect following information and
 * send them to designated managment endpoint once every heartbeatInterval.
 * <ol>
 * <li>Matrics</li>
 * <li>State changes happend on last heartbeatIntervals</li>
 * </ol>
 * 
 * @author Srinath Perera(hperera@cs.indiana.edu)
 */

public class HealthCheckCapability extends AbstractCapability{
    private HeartBeatCapability heartBeatCapability;
    private ScheduledFuture checktaskHandle;
    
    public HealthCheckCapability() {
        super();
    }
 
    public void setProperty(QName name, Object value) throws HasthiException {
        throw new HasthiException("Unsupported property "+name + " set in capability "+ this,FaultCode.InvaliedLocalArgumnet);
    }
   
    public Object getProperty(QName name) throws HasthiException {
        throw new HasthiException("Unsupported property "+name + " requested from capability "+ this,FaultCode.InvaliedLocalArgumnet);
    }

    @Override
    public void init(ManagementAgentContext context, ManagableResource ownedResource,
            CapabilityDescription description) throws HasthiException {
        super.init(context, ownedResource, description);
    }

    public void parentResourceInitialized() {
        for (Capability capability : ownedResource.getCapabilities()) {
            if (WSDMConstants.CAPABILITY_HEARTBEAT.equals(capability.getCapabilityDescription()
                    .getCapabilityURI())) {
                heartBeatCapability = (HeartBeatCapability)capability;
            }
        }
        //We schedule the Heartbeat thread 
        int delay = 1000; // delay for 1 sec.
        int period = 1000 * super.context.getBaseContext().getMngAgentEpochSeconds()*30;
        
        checktaskHandle = context.getScheduledExecutorService().scheduleAtFixedRate(new HealthCheckTask(), delay, period, TimeUnit.MILLISECONDS);
        //timer.scheduleAtFixedRate(new HealthCheckTask(), delay, period);
    }

    public class HealthCheckTask implements Runnable {
        public void run() {
            try {
                ownedResource.getSystemHandle().runResourceHealthCheck();
            } catch (Throwable e) {
                log.error(e);
                try {
                    PiggybackParameterListDocument document = PiggybackParameterListDocument.Factory.newInstance();
                    XmlObject parameterListDocument = document.addNewPiggybackParameterList();
                    XmlBeanUtils.addNameValuePair(parameterListDocument, 
                            WSDMConstants.RESOURCE_STATUS_PARAM, SystemState.CrashedState);
                    heartBeatCapability.sendHeartBeatEvent(document);
                } catch (HasthiException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }finally{
                    try {
                        ownedResource.stop();
                    } catch (HasthiException e1) {
                        log.error(e1);
                    }
                }
            }
        }
    }
    public void stop(){
        checktaskHandle.cancel(true);
        log.info("Shutting down heartbeat capability");
    }
}
